package net.vkits.anjiamiao.application;

import net.vkits.anjiamiao.domain.model.AuthenticationStatus;
import net.vkits.anjiamiao.domain.model.Customer;
import net.vkits.anjiamiao.domain.repository.CustomerRepository;
import net.vkits.anjiamiao.domain.service.CustomerService;
import net.vkits.anjiamiao.domain.service.VerifyCodeService;
import net.vkits.common.dto.User;
import net.vkits.common.exceptions.NoSuchUserException;
import net.vkits.common.storage.StorageService;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Optional;

/**
 * Created by ethan-liu on 16/4/6.
 */
@Service
public class CustomerApplicationService {
    private static final Logger logger = LoggerFactory.getLogger(CustomerApplicationService.class);

    @Resource
    private CustomerRepository customerRepository;
    @Resource
    private CustomerService customerService;
    @Resource
    private VerifyCodeService verifyCodeService;
    @Resource
    private StorageService storageService;

    @Transactional
    public boolean login(String cellPhone, String verifyCode) {
        return verifyCodeService.validateOrCreate(cellPhone, verifyCode);
    }

    @Transactional
    public boolean changeCellphoneNum(String cellPhone, String newPhone, String verifyCode) {
        return verifyCodeService.validateAndChangePhone(cellPhone, newPhone, verifyCode);
    }

    @Transactional
    public void updateUser(String cellPhone, String name, String idCardNo) {
        Optional<Customer> customerOptional = customerRepository.findByCellPhoneNumAndDeletedFalse(cellPhone);
        customerOptional.ifPresent(customer -> {
            customer.updateInfo(name, idCardNo);
            customerRepository.save(customer);
        });
        customerOptional.orElseThrow(NoSuchUserException::new);
    }

    @Transactional
    public void uploadAvatar(MultipartFile file, String cellPhone) {
        // TODO need deny non-jpg file?
        Optional<Customer> customerOptional = customerRepository.findByCellPhoneNumAndDeletedFalse(cellPhone);
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        logger.info("upload file name is: {}", originalFilename);
        logger.info("upload file content type is: {}", file.getContentType());
        logger.info("upload file suffix is: {}", suffix);
        String avatarUrl = getRandomName(suffix);
        customerOptional.ifPresent(customer -> {
            customer.uploadAvatar(avatarUrl);
            storageService.store(file, avatarUrl);
            customerRepository.save(customer);
        });
        customerOptional.orElseThrow(NoSuchUserException::new);
    }

    @Transactional
    public void uploadIdPhotos(MultipartFile file1, MultipartFile file2, String cellPhone) {
        // TODO need deny non-jpg file?
        Optional<Customer> customerOptional = customerRepository.findByCellPhoneNumAndDeletedFalse(cellPhone);
        String originalFilename = file1.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        logger.info("upload file name is: {}", originalFilename);
        logger.info("upload file content type is: {}", file1.getContentType());
        logger.info("upload file suffix is: {}", suffix);
        customerOptional.ifPresent(customer -> {
            customer.uploadIdPhotos(customer.getIdCardNo() + "1." + suffix, customer.getIdCardNo() + "2." + suffix);
            storageService.store(file1, customer.getIdCardNo() + "1." + suffix);
            storageService.store(file2, customer.getIdCardNo() + "2." + suffix);
            customer.setAuthenticationStatus(AuthenticationStatus.Unverified);
            customerRepository.save(customer);
        });
        customerOptional.orElseThrow(NoSuchUserException::new);
    }

    @Transactional
    public void changeAuthenticationStatus(String cellphone, String status, boolean isVIP, boolean isBlock) {
        Optional<Customer> customerOptional = customerRepository.findByCellPhoneNumAndDeletedFalse(cellphone);
        customerOptional.ifPresent(customer -> {
            customer.setAuthenticationStatus(AuthenticationStatus.valueOf(status));
            customer.setIsVIP(isVIP);
            customer.setIsBlock(isBlock);
            customerRepository.save(customer);
        });
    }

    public User getUser(String cellPhone) {
        return customerService.getUser(cellPhone);
    }

    public void deleteUser(String cellPhone) {
        customerService.deleteUser(cellPhone);
    }

    public Page<Customer> getCustomers(Pageable pageable) {
        return customerRepository.findAll(pageable);
    }

    public Optional<Customer> getCustomer(String cellPhoneNum) {
        return customerRepository.findByCellPhoneNumAndDeletedFalse(cellPhoneNum);
    }

    private String getRandomName(String suffix) {
        return RandomStringUtils.randomAlphanumeric(15) + "." + suffix;
    }
}
